package services

import (
	"TaskAssignmentSystem/internal/admin/dao"
	"TaskAssignmentSystem/internal/pkg/modelbase"
	"TaskAssignmentSystem/pkg/db/mysql"
	"TaskAssignmentSystem/pkg/oss"
	"TaskAssignmentSystem/pkg/timehandler"
	"TaskAssignmentSystem/pkg/utils"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"time"
)

type TopicAnswerService struct {
	Tx *gorm.DB
}

func (a *TopicAnswerService) OneInvalidTopic(topicIds []uint) error {
	var txs *gorm.DB
	if a.Tx != nil {
		txs = a.Tx
	} else {
		txs = mysql.GetDB()
	}
	var topics []dao.SystemTopic
	err := txs.Model(&dao.SystemTopic{}).Where("id IN (?)", topicIds).Find(&topics).Error
	fmt.Println(err)
	//修改题目状态
	var topicDao dao.Common[dao.SystemTopic]
	topicDao.Tx = a.Tx
	topicDao.Query = map[string]interface{}{"id": topicIds, "status": []int{0, 1, 2, 3, 4, 5}}
	if err := topicDao.Update(map[string]interface{}{"receiver_id": "", "status": 6, "finish_time": nil}).Error; err != nil {
		return err
	}
	//删除题目相关的答案
	if err := txs.Model(&dao.TopicAnswer{}).Where(map[string]interface{}{"system_topic_id": topicIds}).Delete(&dao.TopicAnswer{}).Error; err != nil {
		return err
	}
	//移除oss的答案
	for _, topic := range topics {
		client := oss.BucketClient{}
		err := client.BatchRemoveFiles(fmt.Sprintf("task-assign/%s/%s", topic.ProjectId, topic.TopicId))
		fmt.Println("error is %v", err)
	}
	return nil

}

//作废题目

func (a *TopicAnswerService) BatchInvalidTopic(topic dao.SystemTopic) error {
	var txs *gorm.DB
	if a.Tx != nil {
		txs = a.Tx
	} else {
		txs = mysql.GetDB()
	}

	//修改题目状态
	var topicDao dao.Common[dao.SystemTopic]
	topicDao.Tx = a.Tx
	topicDao.Query = map[string]interface{}{"id": []uint{topic.Id}, "status": []int{0, 1, 2, 3, 4, 5}}
	if err := topicDao.Update(map[string]interface{}{"receiver_id": "", "status": 6, "finish_time": nil}).Error; err != nil {
		return err
	} else {
		//删除题目相关的答案
		if err := txs.Model(&dao.TopicAnswer{}).Where(map[string]interface{}{"system_topic_id": []uint{topic.Id}}).Delete(&dao.TopicAnswer{}).Error; err != nil {
			return err
		}
		//移除oss的答案
		client := oss.BucketClient{}
		client.BatchRemoveFiles(fmt.Sprintf("task-assign/%s/%s", topic.ProjectId, topic.TopicId))
	}
	return nil

}

// 回归题库

func (a *TopicAnswerService) RegressionQuestionBank(topicIds uint) error {
	var txs *gorm.DB
	if a.Tx != nil {
		txs = a.Tx
	} else {
		txs = mysql.GetDB()
	}

	var topics dao.SystemTopic
	fmt.Println("topicIds", topicIds)
	err := txs.Model(&dao.SystemTopic{}).Where("id = ?", topicIds).First(&topics).Error
	fmt.Println("err is %s", err)
	//清空题目中用户的绑定关系,清除题目中的完成时间
	var topicDao dao.Common[dao.SystemTopic]
	topicDao.Tx = txs
	topicDao.Query = map[string]interface{}{"id": topicIds, "status": []int{0, 1, 2, 3, 4, 5, 6}} //支持未生效的
	topicDao.CustomWhere = append(topicDao.CustomWhere, fmt.Sprintf("end_date_time > '%s'", time.Now().In(utils.LocationZone).Format(timehandler.FormatLayoutTime)))
	update := topicDao.Update(map[string]interface{}{"receiver_id": "", "status": 5, "finish_time": nil, "priority": 1})
	if update.Error != nil {
		return update.Error
	} else {
		if update.RowsAffected == 0 {
			return errors.New("此题无法回归题库, 因题目不在有效期内。")
		}
	}
	//删除题目相关的答案
	if err := txs.Model(&dao.TopicAnswer{}).Where(map[string]interface{}{"system_topic_id": topicIds}).Delete(&dao.TopicAnswer{}).Error; err != nil {
		return err
	}
	//移除oss的答案

	client := oss.BucketClient{}
	err = client.BatchRemoveFiles(fmt.Sprintf("task-assign/%s/%s", topics.ProjectId, topics.TopicId))
	fmt.Println("error is %v", err)
	return nil

}

//批量处理回归题库

func (a *TopicAnswerService) BatchRegressionQuestionBank(topicIds []uint) error {
	var txs *gorm.DB
	if a.Tx != nil {
		txs = a.Tx
	} else {
		txs = mysql.GetDB()
	}

	var topics []dao.SystemTopic
	err := txs.Model(&dao.SystemTopic{}).Where("id IN (?)", topicIds).Find(&topics).Error
	fmt.Println(err)
	//清空题目中用户的绑定关系,清除题目中的完成时间
	var topicDao dao.Common[dao.SystemTopic]
	topicDao.Tx = txs
	topicDao.Query = map[string]interface{}{"id": topicIds, "status": []int{1, 2, 3, 4, 5, 6}}
	topicDao.CustomWhere = append(topicDao.CustomWhere, fmt.Sprintf("end_date_time > '%s'", time.Now().In(utils.LocationZone).Format(timehandler.FormatLayoutTime)))
	update := topicDao.Update(map[string]interface{}{"receiver_id": "", "status": 5, "finish_time": nil, "priority": 1})
	if update.Error != nil {
		return update.Error
	} else {
		if update.RowsAffected == 0 {
			return errors.New("此题无法回归题库")
		}
	}
	//删除题目相关的答案
	if err := txs.Model(&dao.TopicAnswer{}).Where(map[string]interface{}{"system_topic_id": topicIds}).Delete(&dao.TopicAnswer{}).Error; err != nil {
		return err
	}
	//移除oss的答案
	for _, topic := range topics {
		client := oss.BucketClient{}
		err := client.BatchRemoveFiles(fmt.Sprintf("task-assign/%s/%s", topic.ProjectId, topic.TopicId))
		fmt.Println("error is %v", err)
	}
	return nil

}

func (a *TopicAnswerService) DeleteTopicAnswerData2(topicIds []uint) error {
	var txs *gorm.DB
	if a.Tx != nil {
		txs = a.Tx
	} else {
		txs = mysql.GetDB()
	}
	var topics []dao.SystemTopic
	err := txs.Model(&dao.SystemTopic{}).Where("id IN (?)", topicIds).Find(&topics).Error
	fmt.Println(err)
	//删除题目相关的答案
	if err := txs.Model(&dao.TopicAnswer{}).Where(map[string]interface{}{"system_topic_id": topicIds}).Delete(&dao.TopicAnswer{}).Error; err != nil {
		return err
	}
	//移除oss的答案
	for _, topic := range topics {
		client := oss.BucketClient{}
		err := client.BatchRemoveFiles(fmt.Sprintf("task-assign/%s/%s", topic.ProjectId, topic.TopicId))
		fmt.Println("error is %v", err)
	}
	//defer txs.Commit()

	return nil

}

type ExportResponse struct {
	ProjectId     string    `json:"project_id"`
	SystemTopicId uint      `json:"system_topic_id"`
	BatchId       string    `json:"batch_id"`
	PushTopicDate time.Time `json:"push_topic_date"`
	TopicId       string    `json:"topic_id"`
	SN            string    `json:"sn"`
	TopicTitle    string    `json:"topic_title"`
	EffectiveTime time.Time `json:"effective_time"`
	EndDateTime   time.Time `json:"end_date_time"`
	ReceiveTime   time.Time `json:"receive_time"`
	Note          string    `json:"note"`
	Answers       string    `json:"answers"`
	GiveUpReason  string    `json:"give_up_reason"`
	UserId        string    `json:"user_id"`
	RealName      string    `json:"real_name"`
}

//导出答案

/*
 *
 */

func (a *TopicAnswerService) ExportAnswer(topicIds []uint, projectIds []string) (res []ExportResponse, err error) {
	_db := mysql.GetDB()
	tx := _db.Table("tas_system_topic as t")
	if len(topicIds) > 0 {
		tx.Where("t.id IN (?)", topicIds)
	}
	if len(projectIds) > 0 {
		tx.Where("t.project_id IN (?)", projectIds)
	}
	tx = tx.Joins("left join tas_topic_configuration AS c ON t.id = c.system_topic_id")
	tx = tx.Joins("left join tas_topic_note AS n ON n.system_topic_id = t.id")
	tx = tx.Joins("left join tas_topic_answer AS a ON c.id = a.topic_configuration_id")

	topicUserRecordSql := "WITH ranked_tas_topic_user_record AS ( SELECT m.*, ROW_NUMBER() OVER ( PARTITION BY system_topic_id ORDER BY created_at DESC ) AS rn FROM tas_topic_user_record AS m ) SELECT * FROM ranked_tas_topic_user_record WHERE rn = 1 "
	topicUserRecordSubQuery := _db.Raw(topicUserRecordSql)
	tx = tx.Joins("left join (?) AS ur ON ur.system_topic_id = t.id ", topicUserRecordSubQuery)
	tx = tx.Joins("left join tas_system_user AS u ON u.user_id =ur.user_id")
	tx = tx.Order("system_topic_id,cid,nid")
	subQuerySelectStr := "t.project_id AS project_id," +
		"t.created_at AS push_topic_date," +
		"t.id AS system_topic_id," +
		"t.batch_id AS batch_id," +
		"t.topic_id AS topic_id," +
		"a.content AS content," +
		"t.sn AS sn," +
		"t.title AS topic_title," +
		"t.effective_time AS effective_time," +
		"t.end_date_time AS end_date_time," +
		"c.title AS title," +
		"c.tooltip AS tooltip," +
		"n.content AS note," +
		"ur.tp AS tp, " +
		"ur.give_up_reason AS give_up_reason," +
		"ur.user_id AS user_id," +
		"u.real_name AS real_name," +
		"t.finish_time AS receive_time," +
		"c.id AS cid," +
		"c.answer_type AS answer_type," +
		"c.required AS required," +
		"n.id AS nid "
	subQuery := tx.Select(subQuerySelectStr)
	selectStr := "system_topic_id," +
		"ANY_VALUE ( project_id ) AS project_id," +
		"ANY_VALUE ( batch_id ) AS batch_id," +
		"ANY_VALUE ( push_topic_date ) AS push_topic_date," +
		"ANY_VALUE ( d.give_up_reason ) AS give_up_reason," +
		"ANY_VALUE ( d.user_id ) AS user_id," +
		"ANY_VALUE ( d.real_name ) AS real_name," +
		"ANY_VALUE ( topic_id ) AS topic_id," +
		"ANY_VALUE ( sn ) AS sn," +
		"ANY_VALUE ( topic_title ) AS topic_title," +
		"ANY_VALUE ( effective_time ) AS effective_time," +
		"ANY_VALUE ( end_date_time ) AS end_date_time," +
		"MAX( receive_time ) AS receive_time," +
		"GROUP_CONCAT( DISTINCT d.nid, '[#]', d.note SEPARATOR '[@@]' ) AS note," +
		"GROUP_CONCAT( DISTINCT d.answer_type,'[#]',d.required,'[#]',d.title,'[#]',IFNULL(d.content,'') SEPARATOR '[@@]' ) AS answers "
	txs := _db.Table("(?) as d", subQuery).Select(selectStr)

	err = txs.Group("d.system_topic_id").Scan(&res).Error
	return
}

func (a *TopicAnswerService) ExportAnswerTx(topicIds []uint, projectIds []string, _db *gorm.DB) (res []ExportResponse, err error) {
	//_db := mysql.GetDB()
	tx := _db.Table("tas_system_topic as t")
	if len(topicIds) > 0 {
		tx.Where("t.id IN (?)", topicIds)
	}
	if len(projectIds) > 0 {
		tx.Where("t.project_id IN (?)", projectIds)
	}
	tx = tx.Joins("left join tas_topic_configuration AS c ON t.id = c.system_topic_id")
	tx = tx.Joins("left join tas_topic_note AS n ON n.system_topic_id = t.id")
	tx = tx.Joins("left join tas_topic_answer AS a ON c.id = a.topic_configuration_id")

	topicUserRecordSql := "WITH ranked_tas_topic_user_record AS ( SELECT m.*, ROW_NUMBER() OVER ( PARTITION BY system_topic_id ORDER BY created_at DESC ) AS rn FROM tas_topic_user_record AS m ) SELECT * FROM ranked_tas_topic_user_record WHERE rn = 1 "
	topicUserRecordSubQuery := _db.Raw(topicUserRecordSql)
	tx = tx.Joins("left join (?) AS ur ON ur.system_topic_id = t.id ", topicUserRecordSubQuery)
	tx = tx.Joins("left join tas_system_user AS u ON u.user_id =ur.user_id")
	tx = tx.Order("system_topic_id,cid,nid")
	subQuerySelectStr := "t.project_id AS project_id," +
		"t.created_at AS push_topic_date," +
		"t.id AS system_topic_id," +
		"t.batch_id AS batch_id," +
		"t.topic_id AS topic_id," +
		"a.content AS content," +
		"t.sn AS sn," +
		"t.title AS topic_title," +
		"t.effective_time AS effective_time," +
		"t.end_date_time AS end_date_time," +
		"c.title AS title," +
		"c.tooltip AS tooltip," +
		"n.content AS note," +
		"ur.tp AS tp, " +
		"ur.give_up_reason AS give_up_reason," +
		"ur.user_id AS user_id," +
		"u.real_name AS real_name," +
		"t.finish_time AS receive_time," +
		"c.id AS cid," +
		"c.answer_type AS answer_type," +
		"c.required AS required," +
		"n.id AS nid "
	subQuery := tx.Select(subQuerySelectStr)
	selectStr := "system_topic_id," +
		"ANY_VALUE ( project_id ) AS project_id," +
		"ANY_VALUE ( batch_id ) AS batch_id," +
		"ANY_VALUE ( push_topic_date ) AS push_topic_date," +
		"ANY_VALUE ( d.give_up_reason ) AS give_up_reason," +
		"ANY_VALUE ( d.user_id ) AS user_id," +
		"ANY_VALUE ( d.real_name ) AS real_name," +
		"ANY_VALUE ( topic_id ) AS topic_id," +
		"ANY_VALUE ( sn ) AS sn," +
		"ANY_VALUE ( topic_title ) AS topic_title," +
		"ANY_VALUE ( effective_time ) AS effective_time," +
		"ANY_VALUE ( end_date_time ) AS end_date_time," +
		"MAX( receive_time ) AS receive_time," +
		"GROUP_CONCAT( DISTINCT d.nid, '[#]', d.note SEPARATOR '[@@]' ) AS note," +
		"GROUP_CONCAT( DISTINCT d.answer_type,'[#]',d.required,'[#]',d.title,'[#]',IFNULL(d.content,'') SEPARATOR '[@@]' ) AS answers "
	txs := _db.Table("(?) as d", subQuery).Select(selectStr)

	err = txs.Group("d.system_topic_id").Scan(&res).Error
	return
}

type ExportResponseNew struct {
	ProjectId     string    `json:"project_id"`      //项目ID
	PushTopicDate time.Time `json:"push_topic_date"` //发题日期
	SN            string    `json:"sn"`              //题目序号
	TopicId       string    `json:"topic_id"`        //题目ID
	TopicTitle    string    `json:"topic_title"`     //题目名称
	Labels        string    `json:"labels"`          //题目检索标签(如不填写，则默认搜可搜素题目名字)
	EffectiveTime time.Time `json:"effective_time"`  //题目生效时间
	EndDateTime   time.Time `json:"end_date_time"`   //截止时间
	Note          string    `json:"note"`            //备注
	Status        uint      `json:"status"`          //题目状态
	AuditStatus   uint      `json:"audit_status"`    //审核状态
	NickName      string    `json:"nick_name"`       //答主昵称
	RealName      string    `json:"real_name"`       //答主姓名
	TeamNumber    string    `json:"team_number"`     //答主团队编号
	Phone         string    `json:"phone"`           //答主手机号
	Email         string    `json:"email"`           //答主邮箱
	GiveUpReason  string    `json:"give_up_reason"`  //放弃原因
	SystemTopicId uint      `json:"system_topic_id"`
	BatchId       string    `json:"batch_id"`
	ReceiveTime   time.Time `json:"receive_time"`
	Answers       string    `json:"answers"`
	UserId        string    `json:"user_id"`
	RejectTime    time.Time `json:"reject_time"`
	UpdatedAt     time.Time `json:"updated_at"`
}

func (a *TopicAnswerService) ExportAnswerNew(topicIds []uint, projectIds []string) (res []ExportResponseNew, err error) {
	_db := mysql.GetDB()
	tx := _db.Table("tas_system_topic as t")
	if len(topicIds) > 0 {
		tx.Where("t.id IN (?)", topicIds)
	}
	if len(projectIds) > 0 {
		tx.Where("t.project_id IN (?)", projectIds)
	}
	tx = tx.Joins("left join tas_system_user AS u ON u.user_id =t.receiver_id")
	tx = tx.Order("system_topic_id")
	subQuerySelectStr := "t.project_id AS project_id," +
		"t.created_at AS push_topic_date," +
		"t.sn AS sn," +
		"t.topic_id AS topic_id," +
		"t.title AS topic_title," +
		"t.labels AS labels," +
		"t.effective_time AS effective_time," +
		"t.end_date_time AS end_date_time," +
		"t.status AS status," +
		"t.audit_status AS audit_status," +
		"u.nick_name AS nick_name," +
		"u.real_name AS real_name," +
		"u.team_number AS team_number," +
		"u.phone AS phone," +
		"u.email AS email," +
		"t.id AS system_topic_id," +
		"t.receiver_id AS user_id," +
		"t.reject_time AS reject_time," +
		"t.updated_at AS updated_at," +
		"t.batch_id AS batch_id"
	tx.Select(subQuerySelectStr)
	err = tx.Find(&res).Error
	return
}

type TopicAnswerInfo struct {
	Id         uint   `json:"id"`
	Title      string `json:"title"`
	Tooltip    string `json:"tooltip"`
	AnswerType int    `json:"answer_type"`
	Content    string `json:"content"`
	FileUrl    string `json:"file_url"`
	ContentUrl string `json:"content_url"`
}

func (a *TopicAnswerService) GetTopicAnswerInfo(topicId uint) (res []TopicAnswerInfo, err error) {
	var topicAnswerServe dao.Common[TopicAnswerInfo]
	sql := fmt.Sprintf("SELECT a.id,a.title,a.tooltip,a.answer_type,b.content,b.file_url,b.content_url from tas_topic_configuration a left join (SELECT * from tas_topic_answer WHERE id in (SELECT max(id) from tas_topic_answer where system_topic_id = %v GROUP BY topic_configuration_id) ) b on a.id = b.topic_configuration_id WHERE a.system_topic_id = %v ", topicId, topicId)
	if result, err := topicAnswerServe.RawList(sql); err != nil {
		return nil, err
	} else {
		return result, err
	}
}

type TopicNoteResponse struct {
	Note string `json:"note"`
}

func (a *TopicAnswerService) GetTopicNoteInfo(topicId uint) (note string, err error) {
	var topicNoteDao dao.Common[TopicNoteResponse]
	sql := fmt.Sprintf("SELECT GROUP_CONCAT(content SEPARATOR '；') note from tas_topic_note WHERE system_topic_id = %v", topicId)
	if result, err := topicNoteDao.RawOne(sql); err != nil {
		return note, err
	} else {
		return result.Note, err
	}
}

type GetGiveUpReasonResponse struct {
	GiveUpReason string `json:"give_up_reason"`
}

func (a *TopicAnswerService) GetGiveUpReason(topicId uint) (giveUpReason string, err error) {
	var topicAnswerServe dao.Common[GetGiveUpReasonResponse]
	sql := fmt.Sprintf("SELECT give_up_reason FROM tas_topic_user_record ur WHERE id = (SELECT max(id) from tas_topic_answer where system_topic_id = %v and tp = 0 GROUP BY system_topic_id)", topicId)
	if result, err := topicAnswerServe.RawOne(sql); err != nil {
		return giveUpReason, err
	} else {
		return result.GiveUpReason, err
	}
}

type GetTopicStatusInfoResponse struct {
	AnswerStatus   string    `json:"answer_status"`    //答主题目状态
	RejectTime     time.Time `json:"reject_time"`      //驳回时间
	OneStatus      string    `json:"one_status"`       //一审题目状态
	OneAuditStatus string    `json:"one_audit_status"` //一审审核状态
	TwoStatus      string    `json:"two_status"`       //二审题目状态
	TwoAuditStatus string    `json:"two_audit_status"` //二审审核状态
}

func (a *TopicAnswerService) GetTopicStatusInfo(topicId, workProjectId, auditProjectId, finalProjectId string, enumType int) (res *GetTopicStatusInfoResponse, err error) {
	var topicStatusDao dao.Common[GetTopicStatusInfoResponse]
	sql := ""
	//答主项目
	if enumType == modelbase.WorkProj {
		sql += fmt.Sprintf("SELECT a.`status` answer_status,a.reject_time,b.`status` one_status,b.audit_status one_audit_status,")
		sql += fmt.Sprintf("c.`status` two_status,c.audit_status two_audit_status from tas_system_topic a ")
		sql += fmt.Sprintf("LEFT JOIN tas_system_topic b on a.topic_id = b.topic_id and b.project_id = '%v' ", auditProjectId)
		sql += fmt.Sprintf("LEFT JOIN tas_system_topic c on a.topic_id = c.topic_id and c.project_id = '%v' ", finalProjectId)
		sql += fmt.Sprintf("WHERE a.project_id = '%v' and a.topic_id = '%v'", workProjectId, topicId)
	} else if enumType == modelbase.AuditProj {
		//一审项目
		sql += fmt.Sprintf("SELECT a.`status` one_status,a.audit_status one_audit_status,b.`status` answer_status,b.reject_time,")
		sql += fmt.Sprintf("c.`status` two_status,c.audit_status two_audit_status from tas_system_topic a ")
		sql += fmt.Sprintf("LEFT JOIN tas_system_topic b on a.topic_id = b.topic_id and b.project_id = '%v' ", workProjectId)
		sql += fmt.Sprintf("LEFT JOIN tas_system_topic c on a.topic_id = c.topic_id and c.project_id = '%v' ", finalProjectId)
		sql += fmt.Sprintf("WHERE a.project_id = '%v' and a.topic_id = '%v'", auditProjectId, topicId)
	} else if enumType == modelbase.FinalProj {
		//二审项目
		sql += fmt.Sprintf("SELECT a.`status` two_status,a.audit_status two_audit_status,b.`status` answer_status,b.reject_time,")
		sql += fmt.Sprintf("c.`status` one_status,c.audit_status one_audit_status from tas_system_topic a ")
		sql += fmt.Sprintf("LEFT JOIN tas_system_topic b on a.topic_id = b.topic_id and b.project_id = '%v' ", workProjectId)
		sql += fmt.Sprintf("LEFT JOIN tas_system_topic c on a.topic_id = c.topic_id and c.project_id = '%v' ", auditProjectId)
		sql += fmt.Sprintf("WHERE a.project_id = '%v' and a.topic_id = '%v'", finalProjectId, topicId)
	}
	if res, err := topicStatusDao.RawOne(sql); err != nil {
		return nil, err
	} else {
		return &res, err
	}
}
